package com.gary.spring.webContainer.A02;

import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.MethodParameter;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.support.DefaultDataBinderFactory;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.annotation.RequestParamMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author peng_rui
 * @date 2022/7/12
 */
public class A02Start {
    public static void main(String[] args) throws Exception {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig2.class);
        DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
        //准备测试请求
        MockHttpServletRequest request = new MockHttpServletRequest();
        request.setParameter("name", "zhangsan");
        request.setParameter("name2", "lisi");
        request.setParameter("age", "18");
        Map<String, String> uri = new AntPathMatcher()
                .extractUriTemplateVariables("/my-controller2-test/{id}", "/my-controller2-test/123");
        request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uri);

        //2 将控制器方法封装为HandlerMethod
        HandlerMethod handlerMethod = new HandlerMethod(new MyController2(), MyController2.class.getMethod("testParam", String.class, Integer.class, String.class, Long.class));

        //准备类型转换绑定对象
        DefaultDataBinderFactory defaultDataBinderFactory = new DefaultDataBinderFactory(null);

        //准备ModeAndViewContainer 用来存储中间model结果  再参数解析的过程中，由于历史原因，解析过程中可能会产生中间结果，spring统一处理成了MAV对象
        ModelAndViewContainer container = new ModelAndViewContainer();

        //解析每个参数
        MethodParameter[] methodParameters = handlerMethod.getMethodParameters();
        for (MethodParameter methodParameter : methodParameters) {
            //创建参数解析器  beanFactory 工厂类 若参数中有默认值${JAVA_HOME} 这些参数是，可以从beanFactory中获取， false 表示参数注解不是必须的
            RequestParamMethodArgumentResolver argumentResolver = new RequestParamMethodArgumentResolver(beanFactory, false);

            String annotations = Arrays.stream(methodParameter.getMethodAnnotations()).map(a -> a.annotationType().getSimpleName()).collect(Collectors.toList()).toString();
            String str = annotations.length() > 0 ? "@" + annotations + " " : "";
            methodParameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());

            if (argumentResolver.supportsParameter(methodParameter)) {
                //支持参数
                Object v = argumentResolver.resolveArgument(methodParameter, container, new ServletWebRequest(request), defaultDataBinderFactory);
                System.out.println(v.getClass());
                System.out.println("["+methodParameter.getParameterIndex()+"] " + str + methodParameter.getParameterType().getSimpleName() + " " + methodParameter.getParameterName() + " -> " + v);
            } else {
                System.out.println("["+methodParameter.getParameterIndex()+"] " + str + methodParameter.getParameterType().getSimpleName() + " " + methodParameter.getParameterName());
            }


        }

    }
}
